package tech.nuoson.wisdom.infra.internal.ydaospeechtrans;

import java.io.IOException;
import java.util.function.Consumer;

import org.springframework.lang.NonNull;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import lombok.extern.slf4j.Slf4j;
import tech.nuoson.wisdom.domain.foundationmodel.ApiErrorCode;
import tech.nuoson.wisdom.domain.foundationmodel.BusinessException;
import tech.nuoson.wisdom.domain.speechtrans.AbstractSpeechTransMessage;
import tech.nuoson.wisdom.domain.speechtrans.SpeechTransResultMessage;
import tech.nuoson.wisdom.domain.speechtrans.SpeechTransStateMessage;

/**
 * 有道语音翻译 WebSocket 消息处理句柄
 */
@Slf4j
public class YdaoSpeechTransWebSocketHandler extends AbstractWebSocketHandler {
    private Consumer<AbstractSpeechTransMessage<?>> onMessageCallback;
    private WebSocketSession wsSession;

    /**
     * 
     * @param onMessage
     */
    public YdaoSpeechTransWebSocketHandler(@NonNull Consumer<AbstractSpeechTransMessage<?>> onMessage) {
        this.onMessageCallback = onMessage;
    }

    /**
     * 发送一条语音数据
     * 
     * @param message
     */
    public void sendSpeechMessage(@NonNull BinaryMessage message) {
        try {
            log.debug("sending binary message with size: {}", message.getPayloadLength());
            this.wsSession.sendMessage(message);
        } catch (IOException ex) {
            throw new BusinessException(ApiErrorCode.SpeechTransCodeEnum.WS_SEND_MSG_ERROR, ex.toString());
        }

    }

    /**
     * websocket 连接建立后回调
     */
    @Override
    public void afterConnectionEstablished(@NonNull WebSocketSession session) throws Exception {
        log.debug("hashCode: {} afterConnectionEstablished", this.hashCode());
        this.wsSession = session;
        this.onMessageCallback.accept(SpeechTransStateMessage.of(SpeechTransStateMessage.StateCode.SESSION_CONNECTED));
    }

    /**
     * websocket 连接关闭后的回调
     */
    @Override
    public void afterConnectionClosed(@NonNull WebSocketSession session, @NonNull CloseStatus status) throws Exception {
        log.debug("hashCode: {} afterConnectionClosed", this.hashCode());
        this.onMessageCallback.accept(SpeechTransStateMessage.of(
                SpeechTransStateMessage.StateCode.SESSION_DISCONNECTED,
                String.format("code: %d, reason: %s", status.getCode(), status.getReason())));
    }

    /**
     * websocket 连接异常时的回调
     */
    @Override
    public void handleTransportError(@NonNull WebSocketSession session, @NonNull Throwable exception) throws Exception {
        log.debug("hashCode: {} handleTransportError", this.hashCode());
        this.onMessageCallback.accept(SpeechTransStateMessage.of(
                SpeechTransStateMessage.StateCode.SESSION_ERROR, exception.toString()));
    }

    /**
     * websocket 二进制消息接收时的回调
     */
    @Override
    protected void handleBinaryMessage(
            @NonNull WebSocketSession session, @NonNull BinaryMessage message) throws Exception {
        log.debug("received binary message with size: {}", message.getPayloadLength());
    }

    /**
     * websocket 文本消息接收时的回调
     */
    @Override
    protected void handleTextMessage(
            @NonNull WebSocketSession session, @NonNull TextMessage message) throws Exception {
        log.debug("received text message with size: {}", message.getPayloadLength());
        this.onMessageCallback.accept(SpeechTransResultMessage.of(message.getPayload()));
    }
}
